import java.util.ArrayList;
import java.util.List;

public abstract class GUIUnit {
   final String itemString;
   GUIUnit parent;
   final List<GUIUnit> childs = new ArrayList<GUIUnit>();
   final int INDENT_STRING=3;

   static final String[] types={
      "Package", "Frame", "Button", "Pane", "ScrollPane", "Menu", "MenuItem", 
      "List", "Pane"};
   public static GUIUnit create(String id) {
      for(int i=0; i<types.length; i++) {
         if(id.endsWith(types[i])) {
            //final String id=fullId.substring(0, fullId.indexOf(types[i]));
            switch(i) {
            case 0: return new PackageUnit(id); 
            case 1: return new FrameUnit(id);
            case 2: return new ButtonUnit(id);
            case 3: return new PaneUnit(id); 
            default: throw new RuntimeException();
            //case 2: return new DialogUnit(id);
            }
         }
      }
      throw new RuntimeException();
   }
   GUIUnit(String id) {
      itemString = id;
   }
   
   public void setParent(GUIUnit p) { parent=p; }
   public GUIUnit getParent() {
      return parent;
   }

   public void addChild(GUIUnit n) {
      childs.add(n);
      n.setParent(this);
   }
   
   abstract void write(Printer editor);
   
   void writeToChilds(Printer editor) {
      for(int i=0; i<childs.size(); i++) {
         childs.get(i).write(editor);
      }
   }
   
   public String toCode() {
      Printer printer=new Printer();
      write(printer);
      return printer.toString();
   }
   
   public String toString() {
      final StringBuffer buff = new StringBuffer(itemString);
      buff.append("(");
      for (int i = 0; i < childs.size(); i++) {
         buff.append(i).append(". ").append(childs.get(i));
      }
      buff.append(")");
      return buff.toString();
   }
   
   public String getItemString() {
      return itemString;
   }
}

abstract class StructureUnit extends GUIUnit {

   StructureUnit(String id) {
      super(id);
      // TODO Auto-generated constructor stub
   }
   
}
abstract class PropertyUnit extends GUIUnit {

   PropertyUnit(String id) {
      super(id);
      // TODO Auto-generated constructor stub
   }
   
}
class PackageUnit extends GUIUnit {
   public PackageUnit(String id) { super(id); }

   @Override
   public void write(Printer editor) {
      //editor.indent();
      //editor.pn("package ?;", getItemString());
      editor.pn("import ?;", "javax.swing.*");
      for (int i = 0; i < childs.size(); i++) {
         childs.get(i).write(editor);
      }
   }
}
abstract class TopLevelContainerUnit extends GUIUnit {
   public TopLevelContainerUnit(String id) {
      super(id);
   }
   @Override
   public String toString() {
      //final StringBuilder sb=new StringBuilder(); 
      return super.toString();
   }
   
}
class FrameUnit extends TopLevelContainerUnit {
   public FrameUnit(String id) {
      super(id);
   }
   @Override
   public void write(Printer editor) {
      editor.pn("class ? extends ? {", itemString, "JFrame");
      editor.indent();
      editor.pn("public ?() {", itemString);
      editor.indent();
      writeToChilds(editor);
      editor.unindent();
      editor.pn("}");
      editor.unindent();
      editor.pn("}");
      /*
      //[ old method
      final StringBuilder sb=new StringBuilder();
      for(int i=0; i<indent; i++) sb.append(INDENT_STRING);
      sb.append("class")
        .append(" ")
        .append(identifier)
        .append(" ")
        .append("extends JFrame {")
        .append("\n");
      */
   }
}


class PaneUnit extends GUIUnit {
   public PaneUnit(String id) {
      super(id);
   }
   @Override
   public void write(Printer editor) {
      editor.pn("JPanel ?=new JPanel();", getItemString());
      writeToChilds(editor);
      //editor.pn(getParent().getIdentifier()+".add(?);", id);
   }
   
}
class ButtonUnit extends GUIUnit {
   public ButtonUnit(String id) {
      super(id);
   }
   @Override
   public void write(Printer editor) {
      final String text=getItemString().substring(0, getItemString().indexOf("Button"));
      final String id=text.toLowerCase()+"Button";
      editor.pn("final JButton ?=new JButton(\"?\");", id, text);
      editor.pn(getParent().getItemString()+".add(?);", id);
   }
}
/*
class DialogUnit extends TopLevelContainerUnit {} 
 
class ComponentUnit extends TreeNode {}


class ContainerUnit extends ComponentUnit {}
class ScrollPaneUnit extends ContainerUnit {}
*/